/**
  ******************************************************************************
  * @file    mathx_base.h
  * @author  siyun.chen
  * @version v1.0.0
  * @date
  * @brief   适用于嵌入式端的C语言数学拓展库
  ******************************************************************************
  * Change Logs:
  * 2025-07-30      siyun.chen      first version
  ******************************************************************************
  *
  * MIT License
  *
  * Copyright (c) 2025 siyun.chen
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
  * in the Software without restriction, including without limitation the rights
  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  * copies of the Software, and to permit persons to whom the Software is
  * furnished to do so, subject to the following conditions:
  *
  * The above copyright notice and this permission notice shall be included in all
  * copies or substantial portions of the Software.
  *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
  ******************************************************************************
  */
#ifndef _mathx_BASE_H
#define _mathx_BASE_H

#include <stdint.h>
#include <stdlib.h>
#include <math.h>

/**
 * @brief 在数组中查找最小值
 *
 * @param pSrc      输入数组的指针
 * @param blockSize 输入数组的长度
 * @param pResult   返回最小值, 如果为NULL则不会返回该值
 * @param pIndex    返回最小值对应的索引, 如果为NULL则不会返回该值
 *
 * @return 最小值
 */
uint16_t mathx_min_u16(const uint16_t *pSrc, uint32_t blockSize, uint16_t *pResult, uint32_t *pIndex);
uint32_t mathx_min_u32(const uint32_t *pSrc, uint32_t blockSize, uint32_t *pResult, uint32_t *pIndex);
float    mathx_min_f32(const float    *pSrc, uint32_t blockSize, float    *pResult, uint32_t *pIndex);
double   mathx_min_f64(const double   *pSrc, uint32_t blockSize, double   *pResult, uint32_t *pIndex);

/**
 * @brief 在数组中查找最大值
 *
 * @param pSrc      输入数组的指针
 * @param blockSize 输入数组的长度
 * @param pResult   返回最大值, 如果为NULL则不会返回该值
 * @param pIndex    返回最大值对应的索引, 如果为NULL则不会返回该值
 *
 * @return 最大值
 */
uint16_t mathx_max_u16(const uint16_t *pSrc, uint32_t blockSize, uint16_t *pResult, uint32_t *pIndex);
uint32_t mathx_max_u32(const uint32_t *pSrc, uint32_t blockSize, uint32_t *pResult, uint32_t *pIndex);
float    mathx_max_f32(const float    *pSrc, uint32_t blockSize, float    *pResult, uint32_t *pIndex);
double   mathx_max_f64(const double   *pSrc, uint32_t blockSize, double   *pResult, uint32_t *pIndex);

/**
 * @brief 计算数组之和
 *
 * @param pSrc      输入数组的指针
 * @param blockSize 输入数组的大小
 *
 * @return 数组之和
 */
uint64_t mathx_sum_u16(const uint16_t *pSrc, uint32_t blockSize);
uint64_t mathx_sum_u32(const uint32_t *pSrc, uint32_t blockSize);
double   mathx_sum_f32(const float    *pSrc, uint32_t blockSize);
double   mathx_sum_f64(const double   *pSrc, uint32_t blockSize);

/**
 * @brief 计算数组平均值
 *
 * @param pSrc      输入数组的指针
 * @param blockSize 输入数组的大小
 * @param pResult   返回对应类型平均值(如果是整数类型会进行四舍五入操作), 如果为NULL则不会返回该值
 *
 * @return double类型平均值
 */
double mathx_avg_u16(const uint16_t *pSrc, uint32_t blockSize, uint16_t *pResult);
double mathx_avg_u32(const uint32_t *pSrc, uint32_t blockSize, uint32_t *pResult);
double mathx_avg_f32(const float    *pSrc, uint32_t blockSize, float    *pResult);
double mathx_avg_f64(const double   *pSrc, uint32_t blockSize, double   *pResult);

/**
 * @brief 获取数组中位数
 * 
 * @note  此函数会通过调用qsort函数对输入数组进行升序排序，因此会改变原数组的元素顺序。
 * 
 * @param pSrc      输入数组的指针(会改变输入数组顺序)
 * @param blockSize 输入数组的大小
 * @param pResult   返回对应类型中位数(如果是整数类型会进行四舍五入操作), 如果为NULL则不会返回该值
 * 
 * @return 浮点类型中位数
 */
float  mathx_median_u16(uint16_t *pSrc, uint32_t blockSize, uint16_t *pResult);
float  mathx_median_u32(uint32_t *pSrc, uint32_t blockSize, uint32_t *pResult);
float  mathx_median_f32(float    *pSrc, uint32_t blockSize, float    *pResult);
double mathx_median_f64(double   *pSrc, uint32_t blockSize, double   *pResult);

/**
 * @brief 计算总体标准差
 * 
 * @param pSrc      输入数组的指针
 * @param blockSize 输入数组的大小
 * @param pResult   返回总体标准差(如果是整数类型会进行四舍五入操作), 如果为NULL则不会返回该值
 * 
 * @return 总体标准差
 */
float mathx_stdevP_u16(uint16_t *pSrc, uint32_t blockSize, float *pResult);
float mathx_stdevP_u32(uint32_t *pSrc, uint32_t blockSize, float *pResult);
float mathx_stdevP_f32(float    *pSrc, uint32_t blockSize, float *pResult);
float mathx_stdevP_f64(double   *pSrc, uint32_t blockSize, float *pResult);

/**
 * @brief 计算样本标准差
 * 
 * @param pSrc      输入数组的指针
 * @param blockSize 输入数组的大小
 * @param pResult   返回样本标准差(如果是整数类型会进行四舍五入操作), 如果为NULL则不会返回该值
 * 
 * @return 样本标准差
 */
float mathx_stdevS_u16(uint16_t *pSrc, uint32_t blockSize, float *pResult);
float mathx_stdevS_u32(uint32_t *pSrc, uint32_t blockSize, float *pResult);
float mathx_stdevS_f32(float    *pSrc, uint32_t blockSize, float *pResult);
float mathx_stdevS_f64(double   *pSrc, uint32_t blockSize, float *pResult);

#endif //_mathx_UTILS_H
